package net.qiqb.core.domain.event.receiver;

import cn.hutool.core.util.ObjectUtil;
import net.qiqb.core.domain.event.DomainEvent;
import org.apache.dubbo.config.ReferenceConfig;
import org.apache.dubbo.config.ServiceConfig;
import org.apache.dubbo.config.spring.util.DubboBeanUtils;
import org.apache.dubbo.rpc.model.ModuleModel;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import java.util.List;

/**
 * 分布式采用dubbo 实现领域事件接受
 */

public class DubboDomainEventReceiver implements DomainEventReceiver, InitializingBean, ApplicationContextAware {

    private DomainEventModuleService domainEventModuleService;

    @Override
    public List<ReceiveAckResp> receive(DomainEvent domainEvent) {
        // 扫描 应用中是否有监听器监听领域事件
        if (domainEventModuleService == null) {
            throw new RuntimeException("找不到 dubbo 的领域事件服务");
        }
        final List<ReceiveAckResp> receive = domainEventModuleService.receive(domainEvent.getPayload().getClass().getName(),ObjectUtil.serialize(domainEvent));
        return receive;
    }


    @Override
    public void afterPropertiesSet() throws Exception {
        String projectName = this.applicationContext.getEnvironment().getProperty("project.name");
        // 添加dubbo
        // @DubboService(group = "${project.name}",scope = "remote")
        ModuleModel moduleModel = DubboBeanUtils.getModuleModel(applicationContext);
        ServiceConfig<DomainEventModuleService> serviceConfig = new ServiceConfig<>();
        serviceConfig.setInterface(DomainEventModuleService.class);
        serviceConfig.setRef(applicationContext.getBean(DomainEventModuleServiceImpl.class));
        serviceConfig.setGroup(projectName);
        serviceConfig.setScope("remote");
        moduleModel.getConfigManager().addService(serviceConfig);


        ReferenceConfig<DomainEventModuleService> reference = new ReferenceConfig<>();
        reference.setInterface(DomainEventModuleService.class);
        reference.setGroup("*");
        reference.setMerger("true");
        reference.setCheck(false);
        moduleModel.getConfigManager().addReference(reference);
        this.domainEventModuleService = reference.get();
    }

    private ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}